﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
namespace LitTools
{
    public partial class TutorialManager : Singleton<TutorialManager>, ISingleton
    {
        int ISingleton.Order => 1;

        void ISingleton.OnInit()
        {
            //添加TutorialItem
            CreateTutorialItems();
            CreateSoftTutorialItems();
            eventListener = new TutorialListener();
            eventListener.AddListener();
        }

        void ISingleton.OnUpdate()
        {
            if (!isOpen) return;
            if (curTutorialItem != null)
            {
                curTutorialItem.OnUpdate();
            }
            else
            {
                //软引导检查
                if (softTutorialList != null)
                {
                    for (int i = 0; i < softTutorialList.Count; i++)
                    {
                        if (softTutorialList[i].CheckFunc())
                        {
                            ShowTutorial(softTutorialList[i].id);
                            break;
                        }
                    }
                }
            }
        }

        void ISingleton.OnDestroy()
        {
            eventListener?.RemoveListener();
        }
    }

    public partial class TutorialManager
    {
        /// <summary>
        /// 是否正在显示引导
        /// </summary>
        public bool IsShowing { get; private set; } = false;

        private TutorialItemBase curTutorialItem;
        private Dictionary<string, TutorialItemBase> tutorialDict;
        private List<TutorialItem_Soft> softTutorialList;
        private TutorialStorage storage;
        private List<string> cancheIds;
        private bool isOpen = true;
        private bool openLog = true;
        private TutorialListener eventListener;

        private void CreateTutorialItems()
        {
            tutorialDict = new Dictionary<string, TutorialItemBase>();
            TutorialItemCreater creater = new TutorialItemCreater();
            Type type = creater.GetType();
            MethodInfo[] methods = type.GetMethods();
            for (int i = 0; i < methods.Length; i++)
            {
                var attributes = methods[i].GetCustomAttributes(typeof(TutorialItemCreaterAttribute), true);
                if (attributes.Length > 0)
                {
                    var attribute = attributes[i] as TutorialItemCreaterAttribute;
                    var item = methods[i].Invoke(creater, null) as TutorialItemBase;
                    item.id = attribute.Id;
                    tutorialDict.Add(attribute.Id, item);
                    if (openLog)
                    {
                        Debug.Log($"[TutorialManager] add tutorialItem id:{item.id}");
                    }
                }
            }
        }

        private void CreateSoftTutorialItems()
        {
            softTutorialList ??= new List<TutorialItem_Soft>();
            var keys = tutorialDict.Keys.ToList();
            for (int i = 0; i < keys.Count; i++)
            {
                if (tutorialDict[keys[i]] is TutorialItem_Soft soft)
                    softTutorialList.Add(soft);
            }
        }

        /// <summary>
        /// 获取TutorialItem
        /// </summary>
        /// <param name="tutorialId"></param>
        /// <returns></returns>
        public TutorialItemBase GetTutorialItem(string tutorialId)
        {
            if (tutorialDict.ContainsKey(tutorialId))
            {
                return tutorialDict[tutorialId];
            }
            else
            {
                Debug.LogError($"[TuorialManager] {tutorialId} 对应的Item不存在");
                return null;
            }
        }

        /// <summary>
        /// 引导是否完成
        /// </summary>
        /// <param name="tutorialId"></param>
        /// <returns></returns>
        public bool IsTutorialItemFinish(string tutorialId)
        {
            if (!isOpen) return true;
            if (storage.finishTutorialIds == null)
                return false;
            if (storage.finishTutorialIds.Count <= 0)
                return false;
            if (!storage.finishTutorialIds.Contains(tutorialId))
                return false;
            return true;
        }

        /// <summary>
        /// 引导是否正在展示
        /// </summary>
        /// <param name="tutorialId"></param>
        /// <returns></returns>
        public bool IsTutorialShowing(string tutorialId)
        {
            if (!isOpen) return false;
            if (curTutorialItem == null) return false;
            return curTutorialItem.id == tutorialId;
        }

        /// <summary>
        /// 显示引导
        /// </summary>
        /// <param name="tutorialId">引导Id</param>
        public bool ShowTutorial(string tutorialId)
        {
            if (!isOpen) return false;
            if (!tutorialDict.ContainsKey(tutorialId))
            {
                if (openLog)
                    Debug.LogError($"[TutorialManager] 引导 {tutorialId} 不存在");
                return false;
            }
            if (IsTutorialItemFinish(tutorialId))
            {
                if (openLog)
                    Debug.Log($"[TutorialManager] 引导 {tutorialId} 已结束");
                return false;
            }
            if (curTutorialItem != null
                && curTutorialItem is TutorialItem_Soft soft)
            {
                //如果当前有软引导，立刻更新一下
                soft.OnUpdate();
            }
            if (curTutorialItem != null)
            {
                if (openLog)
                    Debug.Log($"[TutorialManager] 引导 {tutorialId} 当前正在显示引导 {curTutorialItem.id}");
                return false;
            }

            if (openLog)
                Debug.Log($"[TutorialManager] 显示引导{tutorialId}");
            curTutorialItem = tutorialDict[tutorialId];
            curTutorialItem.OnShow();

            SaveOnShowTutorial(tutorialId);
            IsShowing = true;
            return true;
        }

        private void SaveOnShowTutorial(string tutorialId)
        {
            if (curTutorialItem.finishImmediately)
            {
                //展示时立刻结束则不记录当前Id并把引导加入完成队列
                storage.curTutotialId = "";
                storage.finishTutorialIds ??= new List<string>();
                if (cancheIds != null && cancheIds.Count > 0)
                {
                    for (int i = 0; i < cancheIds.Count; i++)
                    {
                        storage.finishTutorialIds.Add(cancheIds[i]);
                    }
                }
                storage.finishTutorialIds.Add(tutorialId);
                //Debug.Log($"[TutorialManager] 立刻保存引导 {tutorialId}");
            }
            else
            {
                if (cancheIds != null && cancheIds.Count > 0)
                {
                    //有未保存的进度则不记录当前Id
                    //Debug.Log($"[TutorialManager] 有未保存的进度则不记录当前Id {tutorialId}");
                }
                else
                {
                    storage.curTutotialId = curTutorialItem.id;
                    //Debug.Log($"[TutorialManager] 保存到当前引导 {tutorialId}");
                }
            }
        }

        /// <summary>
        /// 隐藏引导
        /// </summary>
        /// <param name="tutorialId"></param>
        /// <returns></returns>
        public bool HideTutorial(string tutorialId)
        {
            if (!isOpen) return false;
            if (!tutorialDict.ContainsKey(tutorialId))
            {
                Debug.LogError($"[TutorialManager] 引导 {tutorialId} 不存在");
                return false;
            }
            if (curTutorialItem == null)
            {
                //Debug.Log($"[TutorialManager] 引导 {tutorialId} 与当前引导为空");
                return false;
            }
            if (curTutorialItem.id != tutorialId)
            {
                //Debug.Log($"[TutorialManager] 引导 {tutorialId} 与当前 {curTutorialItem.id} 不一致");
                return false;
            }
            Debug.Log($"[TutorialManager] 隐藏引导 {tutorialId}");
            if (curTutorialItem is TutorialItem_Soft)
            {
                //软引导不保存状态
                //Debug.Log($"[TutorialManager] 软引导不保存状态 {tutorialId}");
            }
            else
            {
                SaveOnHideTutorial(tutorialId);
            }
            //关闭引导
            IsShowing = false;
            var temp = curTutorialItem;
            curTutorialItem = null;
            temp.OnHide();
            return true;
        }

        private void SaveOnHideTutorial(string tutorialId)
        {
            //缓存完成Id
            cancheIds ??= new List<string>();
            if (!cancheIds.Contains(tutorialId))
                cancheIds.Add(tutorialId);
            //立刻保存状态
            if (curTutorialItem.saveImmediately)
            {
                storage.finishTutorialIds ??= new List<string>();
                for (int i = 0; i < cancheIds.Count; i++)
                {
                    if (!storage.finishTutorialIds.Contains(cancheIds[i]))
                        storage.finishTutorialIds.Add(cancheIds[i]);
                }
                cancheIds.Clear();
            }
        }

        /// <summary>
        /// 清除数据
        /// </summary>
        public void ClearData()
        {

        }
    }
}
